home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / win / wgraph.c < prev    next >
C/C++ Source or Header  |  1998-12-04  |  47KB  |  1,657 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: wgraph.c,v 1.14 1998/03/22 23:32:00 drd Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - win/wgraph.c */
  6. /*[
  7.  * Copyright 1992, 1993, 1998   Maurice Castro, Russell Lang
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and
  12.  * that both that copyright notice and this permission notice appear
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the complete modified source code.  Modifications are to
  17.  * be distributed as patches to the released version.  Permission to
  18.  * distribute binaries produced by compiling modified sources is granted,
  19.  * provided you
  20.  *   1. distribute the corresponding source modifications from the
  21.  *    released version in the form of a patch file along with the binaries,
  22.  *   2. add special version identification to distinguish your version
  23.  *    in addition to the base release version number,
  24.  *   3. provide your name and address as the primary contact for the
  25.  *    support of your modified version, and
  26.  *   4. retain our contact information in regard to use of the base
  27.  *    software.
  28.  * Permission to distribute the released version of the source code along
  29.  * with corresponding source modifications in the form of a patch file is
  30.  * granted with same provisions 2 through 4 for binary distributions.
  31.  *
  32.  * This software is provided "as is" without express or implied warranty
  33.  * to the extent permitted by applicable law.
  34. ]*/
  35.  
  36. /*
  37.  * AUTHORS
  38.  * 
  39.  *   Maurice Castro
  40.  *   Russell Lang
  41.  * 
  42.  * Send your comments or suggestions to 
  43.  *  info-gnuplot@dartmouth.edu.
  44.  * This is a mailing list; to join it send a note to 
  45.  *  majordomo@dartmouth.edu.  
  46.  * Send bug reports to
  47.  *  bug-gnuplot@dartmouth.edu.
  48.  */
  49.  
  50. #define STRICT
  51. #include <windows.h>
  52. #include <windowsx.h>
  53. #if WINVER >= 0x030a
  54. #include <commdlg.h>
  55. #endif
  56. #ifndef __MSC__
  57. #include <mem.h>
  58. #endif
  59. #include <stdio.h>
  60. #include <string.h>
  61. #include "wgnuplib.h"
  62. #include "wresourc.h"
  63. #include "wcommon.h"
  64.  
  65. LRESULT CALLBACK WINEXPORT WndGraphProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  66.  
  67. void ReadGraphIni(LPGW lpgw);
  68.  
  69. /* ================================== */
  70.  
  71. #define MAXSTR 255
  72.  
  73. #define WGDEFCOLOR 15
  74. COLORREF wginitcolor[WGDEFCOLOR] =  {
  75.     RGB(255,0,0),    /* red */
  76.     RGB(0,255,0),    /* green */
  77.     RGB(0,0,255),    /* blue */
  78.     RGB(255,0,255), /* magenta */
  79.     RGB(0,0,128),    /* dark blue */
  80.     RGB(128,0,0),    /* dark red */
  81.     RGB(0,128,128),    /* dark cyan */
  82.     RGB(0,0,0),    /* black */
  83.     RGB(128,128,128), /* grey */
  84.     RGB(0,128,64),    /* very dark cyan */
  85.     RGB(128,128,0), /* dark yellow */
  86.     RGB(128,0,128),    /* dark magenta */
  87.     RGB(192,192,192), /* light grey */
  88.     RGB(0,255,255),    /* cyan */
  89.     RGB(255,255,0),    /* yellow */
  90. };
  91. #define WGDEFSTYLE 5
  92. int wginitstyle[WGDEFSTYLE] = {PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT};
  93.  
  94. /* ================================== */
  95.  
  96. /* destroy memory blocks holding graph operations */
  97. void
  98. DestroyBlocks(LPGW lpgw)
  99. {
  100.     struct GWOPBLK *this, *next;
  101.     struct GWOP FAR *gwop;
  102.     unsigned int i;
  103.  
  104.     this = lpgw->gwopblk_head;
  105.     while (this != NULL) {
  106.         next = this->next;
  107.         if (!this->gwop) {
  108.             this->gwop = (struct GWOP FAR *)GlobalLock(this->hblk);
  109.         }
  110.         if (this->gwop) {
  111.             /* free all text strings within this block */
  112.             gwop = this->gwop;
  113.             for (i=0; i<GWOPMAX; i++) {
  114.                 if (gwop->htext)
  115.                     LocalFree(gwop->htext);
  116.                 gwop++;
  117.             }
  118.         }
  119.         GlobalUnlock(this->hblk);
  120.         GlobalFree(this->hblk);
  121.         LocalFreePtr(this);
  122.         this = next;
  123.     }
  124.     lpgw->gwopblk_head = NULL;
  125.     lpgw->gwopblk_tail = NULL;
  126.     lpgw->nGWOP = 0;
  127. }
  128.         
  129.     
  130. /* add a new memory block for graph operations */
  131. /* returns TRUE if block allocated */
  132. BOOL 
  133. AddBlock(LPGW lpgw)
  134. {
  135. HGLOBAL hblk;
  136. struct GWOPBLK *next, *this;
  137.  
  138.     /* create new block */
  139.     next = (struct GWOPBLK *)LocalAllocPtr(LHND, sizeof(struct GWOPBLK) );
  140.     if (next == NULL)
  141.         return FALSE;
  142.     hblk = GlobalAlloc(GHND, GWOPMAX*sizeof(struct GWOP));
  143.     if (hblk == NULL)
  144.         return FALSE;
  145.     next->hblk = hblk;
  146.     next->gwop = (struct GWOP FAR *)NULL;
  147.     next->next = (struct GWOPBLK *)NULL;
  148.     next->used = 0;
  149.     
  150.     /* attach it to list */
  151.     this = lpgw->gwopblk_tail;
  152.     if (this == NULL) {
  153.         lpgw->gwopblk_head = next;
  154.     }
  155.     else {
  156.         this->next = next;
  157.         this->gwop = (struct GWOP FAR *)NULL;
  158.         GlobalUnlock(this->hblk);
  159.     }
  160.     lpgw->gwopblk_tail = next;
  161.     next->gwop = (struct GWOP FAR *)GlobalLock(next->hblk);
  162.     if (next->gwop == (struct GWOP FAR *)NULL)
  163.         return FALSE;
  164.         
  165.     return TRUE;
  166. }
  167.  
  168.  
  169. void WDPROC
  170. GraphOp(LPGW lpgw, WORD op, WORD x, WORD y, LPSTR str)
  171. {
  172.     struct GWOPBLK *this;
  173.     struct GWOP FAR *gwop;
  174.     char *npstr;
  175.     
  176.     this = lpgw->gwopblk_tail;
  177.     if ( (this==NULL) || (this->used >= GWOPMAX) ) {
  178.         /* not enough space so get new block */
  179.         if (!AddBlock(lpgw))
  180.             return;
  181.         this = lpgw->gwopblk_tail;
  182.     }
  183.     gwop = &this->gwop[this->used];
  184.     gwop->op = op;
  185.     gwop->x = x;
  186.     gwop->y = y;
  187.     gwop->htext = 0;
  188.     if (str) {
  189.         gwop->htext = LocalAlloc(LHND, _fstrlen(str)+1);
  190.         npstr = LocalLock(gwop->htext);
  191.         if (gwop->htext && (npstr != (char *)NULL))
  192.             lstrcpy(npstr, str);
  193.         LocalUnlock(gwop->htext);
  194.     }
  195.     this->used++;
  196.     lpgw->nGWOP++;
  197.     return;
  198. }
  199.  
  200. /* ================================== */
  201.  
  202. void WDPROC
  203. GraphInit(LPGW lpgw)
  204. {
  205.     HMENU sysmenu;
  206.     WNDCLASS wndclass;
  207.     char buf[80];
  208.  
  209.     if (!lpgw->hPrevInstance) {
  210.         wndclass.style = CS_HREDRAW | CS_VREDRAW;
  211.         wndclass.lpfnWndProc = WndGraphProc;
  212.         wndclass.cbClsExtra = 0;
  213.         wndclass.cbWndExtra = 2 * sizeof(void FAR *);
  214.         wndclass.hInstance = lpgw->hInstance;
  215.         wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  216.         wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  217.         wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  218.         wndclass.lpszMenuName = NULL;
  219.         wndclass.lpszClassName = szGraphClass;
  220.         RegisterClass(&wndclass);
  221.     }
  222.  
  223.     ReadGraphIni(lpgw);
  224.  
  225.     lpgw->hWndGraph = CreateWindow(szGraphClass, lpgw->Title,
  226.         WS_OVERLAPPEDWINDOW,
  227.         lpgw->Origin.x, lpgw->Origin.y,
  228.         lpgw->Size.x, lpgw->Size.y,
  229.         NULL, NULL, lpgw->hInstance, lpgw);
  230.  
  231.     lpgw->hPopMenu = CreatePopupMenu();
  232.     AppendMenu(lpgw->hPopMenu, MF_STRING | (lpgw->graphtotop ? MF_CHECKED : MF_UNCHECKED), 
  233.         M_GRAPH_TO_TOP, "Bring to &Top");
  234.     AppendMenu(lpgw->hPopMenu, MF_STRING | (lpgw->color ? MF_CHECKED : MF_UNCHECKED), 
  235.         M_COLOR, "C&olor");
  236.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_COPY_CLIP, "&Copy to Clipboard");
  237. #if WINVER >= 0x030a
  238.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_BACKGROUND, "&Background...");
  239.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_CHOOSE_FONT, "Choose &Font...");
  240.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_LINESTYLE, "&Line Styles...");
  241. #endif
  242.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_PRINT, "&Print...");
  243.     if (lpgw->IniFile != (LPSTR)NULL) {
  244.         wsprintf(buf,"&Update %s",lpgw->IniFile);
  245.         AppendMenu(lpgw->hPopMenu, MF_STRING, M_WRITEINI, (LPSTR)buf);
  246.     }
  247.  
  248.     /* modify the system menu to have the new items we want */
  249.     sysmenu = GetSystemMenu(lpgw->hWndGraph,0);
  250.     AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
  251.     AppendMenu(sysmenu, MF_POPUP, (UINT)lpgw->hPopMenu, "&Options");
  252.     AppendMenu(sysmenu, MF_STRING, M_ABOUT, "&About");
  253.  
  254.     if (!IsWindowVisible(lpgw->lptw->hWndParent)) {
  255.         AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
  256.         AppendMenu(sysmenu, MF_STRING, M_COMMANDLINE, "C&ommand Line");
  257.     }
  258.  
  259.     ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);
  260. }
  261.  
  262. /* close a graph window */
  263. void WDPROC
  264. GraphClose(LPGW lpgw)
  265. {
  266.     /* close window */
  267.     if (lpgw->hWndGraph)
  268.         DestroyWindow(lpgw->hWndGraph);
  269.     TextMessage();
  270.     lpgw->hWndGraph = NULL;
  271.  
  272.     lpgw->locked = TRUE;
  273.     DestroyBlocks(lpgw);
  274.     lpgw->locked = FALSE;
  275.  
  276. }
  277.     
  278.  
  279. void WDPROC
  280. GraphStart(LPGW lpgw, double pointsize)
  281. {
  282.     lpgw->locked = TRUE;
  283.     DestroyBlocks(lpgw);
  284.         lpgw->org_pointsize = pointsize;
  285.     if ( !lpgw->hWndGraph || !IsWindow(lpgw->hWndGraph) )
  286.         GraphInit(lpgw);
  287.     if (IsIconic(lpgw->hWndGraph))
  288.         ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);
  289.     if (lpgw->graphtotop)
  290.         BringWindowToTop(lpgw->hWndGraph);
  291.  
  292. }
  293.         
  294. void WDPROC
  295. GraphEnd(LPGW lpgw)
  296. {
  297. RECT rect;
  298.     GetClientRect(lpgw->hWndGraph, &rect);
  299.     InvalidateRect(lpgw->hWndGraph, (LPRECT) &rect, 1);
  300.     lpgw->locked = FALSE;
  301.     UpdateWindow(lpgw->hWndGraph);
  302. }
  303.  
  304. void WDPROC
  305. GraphResume(LPGW lpgw)
  306. {
  307.         lpgw->locked = TRUE;
  308. }
  309.  
  310. void WDPROC
  311. GraphPrint(LPGW lpgw)
  312. {
  313.     if (lpgw->hWndGraph && IsWindow(lpgw->hWndGraph))
  314.         SendMessage(lpgw->hWndGraph,WM_COMMAND,M_PRINT,0L);
  315. }
  316.  
  317. void WDPROC
  318. GraphRedraw(LPGW lpgw)
  319. {
  320.     if (lpgw->hWndGraph && IsWindow(lpgw->hWndGraph))
  321.         SendMessage(lpgw->hWndGraph,WM_COMMAND,M_REBUILDTOOLS,0L);
  322. }
  323. /* ================================== */
  324.  
  325. void
  326. StorePen(LPGW lpgw, int i, COLORREF ref, int colorstyle, int monostyle)
  327. {
  328.     LOGPEN FAR *plp;
  329.  
  330.     plp = &lpgw->colorpen[i];
  331.     plp->lopnColor = ref;
  332.     if (colorstyle < 0) {
  333.         plp->lopnWidth.x = -colorstyle;
  334.         plp->lopnStyle = 0;
  335.     }
  336.     else {
  337.         plp->lopnWidth.x = 1;
  338.         plp->lopnStyle = colorstyle % 5;
  339.     }
  340.     plp->lopnWidth.y = 0;
  341.  
  342.     plp = &lpgw->monopen[i];
  343.     plp->lopnColor = RGB(0,0,0);
  344.     if (monostyle < 0) {
  345.         plp->lopnWidth.x = -monostyle;
  346.             plp->lopnStyle = 0;
  347.     }
  348.     else {
  349.         plp->lopnWidth.x = 1;
  350.         plp->lopnStyle = monostyle % 5;
  351.     }
  352.     plp->lopnWidth.y = 0;
  353. }
  354.  
  355. void
  356. MakePens(LPGW lpgw, HDC hdc)
  357. {
  358.     int i;
  359.  
  360.     if ((GetDeviceCaps(hdc,NUMCOLORS) == 2) || !lpgw->color) {
  361.         /* Monochrome Device */
  362.         /* create border pens */
  363.         lpgw->hbpen = CreatePenIndirect((LOGPEN FAR *)&lpgw->monopen[0]);    /* border */
  364.         lpgw->hapen = CreatePenIndirect((LOGPEN FAR *)&lpgw->monopen[1]);     /* axis */
  365.         /* create drawing pens */
  366.         for (i=0; i<WGNUMPENS; i++)
  367.         {
  368.             lpgw->hpen[i] = CreatePenIndirect((LOGPEN FAR *)&lpgw->monopen[i+2]);
  369.             }
  370.         /* find number of solid, unit width line styles */
  371.         for (i=0; i<WGNUMPENS && lpgw->monopen[i+2].lopnStyle==PS_SOLID
  372.             && lpgw->monopen[i+2].lopnWidth.x==1; i++) ;
  373.         lpgw->numsolid = i ? i : 1;    /* must be at least 1 */
  374.         lpgw->hbrush = CreateSolidBrush(RGB(255,255,255));
  375.         for (i=0; i<WGNUMPENS+2; i++) 
  376.                 lpgw->colorbrush[i] = CreateSolidBrush(RGB(0,0,0));
  377.     }
  378.     else {
  379.         /* Color Device */
  380.         /* create border pens */
  381.         lpgw->hbpen = CreatePenIndirect((LOGPEN FAR *)&lpgw->colorpen[0]);    /* border */
  382.         lpgw->hapen = CreatePenIndirect((LOGPEN FAR *)&lpgw->colorpen[1]);     /* axis */
  383.         /* create drawing pens */
  384.         for (i=0; i<WGNUMPENS; i++)
  385.         {
  386.             lpgw->hpen[i] = CreatePenIndirect((LOGPEN FAR *)&lpgw->colorpen[i+2]);
  387.             }
  388.         /* find number of solid, unit width line styles */
  389.         for (i=0; i<WGNUMPENS && lpgw->colorpen[i+2].lopnStyle==PS_SOLID
  390.             && lpgw->colorpen[i+2].lopnWidth.x==1; i++) ;
  391.         lpgw->numsolid = i ? i : 1;    /* must be at least 1 */
  392.         lpgw->hbrush = CreateSolidBrush(lpgw->background);
  393.         for (i=0; i<WGNUMPENS+2; i++) 
  394.                 lpgw->colorbrush[i] = CreateSolidBrush(lpgw->colorpen[i].lopnColor);
  395.     }
  396. }
  397.  
  398. void
  399. DestroyPens(LPGW lpgw)
  400. {
  401.     int i;
  402.  
  403.     DeleteObject(lpgw->hbrush);
  404.     DeleteObject(lpgw->hbpen);
  405.     DeleteObject(lpgw->hapen);
  406.     for (i=0; i<WGNUMPENS; i++)
  407.         DeleteObject(lpgw->hpen[i]);
  408.     for (i=0; i<WGNUMPENS+2; i++)
  409.         DeleteObject(lpgw->colorbrush[i]);
  410. }
  411.  
  412. /* ================================== */
  413.  
  414. void
  415. MakeFonts(LPGW lpgw, LPRECT lprect, HDC hdc)
  416. {
  417.     LOGFONT lf;
  418.     HFONT hfontold;
  419.     TEXTMETRIC tm;
  420.     int result;
  421.     char FAR *p;
  422.     int cx, cy;
  423.  
  424.     lpgw->rotate = FALSE;
  425.     _fmemset(&lf, 0, sizeof(LOGFONT));
  426.     _fstrncpy(lf.lfFaceName,lpgw->fontname,LF_FACESIZE);
  427.     lf.lfHeight = -MulDiv(lpgw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  428.     lf.lfCharSet = DEFAULT_CHARSET;
  429.     if ( (p = _fstrstr(lpgw->fontname," Italic")) != (LPSTR)NULL ) {
  430.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  431.         lf.lfItalic = TRUE;
  432.     }
  433.     if ( (p = _fstrstr(lpgw->fontname," Bold")) != (LPSTR)NULL ) {
  434.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  435.         lf.lfWeight = FW_BOLD;
  436.     }
  437.  
  438.     if (lpgw->hfonth == 0) {
  439.         lpgw->hfonth = CreateFontIndirect((LOGFONT FAR *)&lf);
  440.     }
  441.  
  442.     if (lpgw->hfontv == 0) {
  443.         lf.lfEscapement = 900;
  444.         lf.lfOrientation = 900;
  445.         lpgw->hfontv = CreateFontIndirect((LOGFONT FAR *)&lf);
  446.     }
  447.  
  448.     /* save text size */
  449.     hfontold = SelectObject(hdc, lpgw->hfonth);
  450. #ifdef WIN32
  451.     {
  452.     SIZE size;
  453.     GetTextExtentPoint(hdc,"0123456789",10, (LPSIZE)&size);
  454.     cx = size.cx;
  455.     cy = size.cy;
  456.     }
  457. #else
  458.     {
  459.     DWORD extent;
  460.     extent = GetTextExtent(hdc,"0123456789",10);
  461.     cx = LOWORD(extent);
  462.     cy = HIWORD(extent);
  463.     }
  464. #endif
  465.     lpgw->vchar = MulDiv(cy,lpgw->ymax,lprect->bottom - lprect->top);
  466.     lpgw->hchar = MulDiv(cx/10,lpgw->xmax,lprect->right - lprect->left);
  467.         /* CMW: Base tick size on character size */
  468.         lpgw->htic = lpgw->hchar/2;
  469.         cy = MulDiv(cx/20, GetDeviceCaps(hdc,LOGPIXELSY), GetDeviceCaps(hdc,LOGPIXELSX));
  470.         lpgw->vtic = MulDiv(cy,lpgw->ymax,lprect->bottom - lprect->top);
  471.     /* find out if we can rotate text 90deg */
  472.     SelectObject(hdc, lpgw->hfontv);
  473.     result = GetDeviceCaps(hdc, TEXTCAPS);
  474.     if ((result & TC_CR_90) || (result & TC_CR_ANY))
  475.         lpgw->rotate = 1;
  476.     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  477.     if (tm.tmPitchAndFamily & TMPF_VECTOR)
  478.         lpgw->rotate = 1;    /* vector fonts can all be rotated */
  479. #if WINVER >=0x030a
  480.     if (tm.tmPitchAndFamily & TMPF_TRUETYPE)
  481.         lpgw->rotate = 1;    /* truetype fonts can all be rotated */
  482. #endif
  483.     SelectObject(hdc, hfontold);
  484.     return;
  485. }
  486.  
  487. void
  488. DestroyFonts(LPGW lpgw)
  489. {
  490.     if (lpgw->hfonth) {
  491.         DeleteObject(lpgw->hfonth);
  492.         lpgw->hfonth = 0;
  493.     }
  494.     if (lpgw->hfontv) {
  495.         DeleteObject(lpgw->hfontv);
  496.         lpgw->hfontv = 0;
  497.     }
  498.     return;
  499. }
  500.  
  501. void
  502. SetFont(LPGW lpgw, HDC hdc)
  503. {
  504.     if (lpgw->rotate && lpgw->angle) {
  505.         if (lpgw->hfontv)
  506.             SelectObject(hdc, lpgw->hfontv);
  507.     }
  508.     else {
  509.         if (lpgw->hfonth)
  510.             SelectObject(hdc, lpgw->hfonth);
  511.     }
  512.     return;
  513. }
  514.  
  515. void
  516. SelFont(LPGW lpgw) {
  517. #if WINVER >= 0x030a
  518.     LOGFONT lf;
  519.     CHOOSEFONT cf;
  520.     HDC hdc;
  521.     char lpszStyle[LF_FACESIZE]; 
  522.     char FAR *p;
  523.  
  524.     /* Set all structure fields to zero. */
  525.     _fmemset(&cf, 0, sizeof(CHOOSEFONT));
  526.     _fmemset(&lf, 0, sizeof(LOGFONT));
  527.     cf.lStructSize = sizeof(CHOOSEFONT);
  528.     cf.hwndOwner = lpgw->hWndGraph;
  529.     _fstrncpy(lf.lfFaceName,lpgw->fontname,LF_FACESIZE);
  530.     if ( (p = _fstrstr(lpgw->fontname," Bold")) != (LPSTR)NULL ) {
  531.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  532.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  533.     }
  534.     else if ( (p = _fstrstr(lpgw->fontname," Italic")) != (LPSTR)NULL ) {
  535.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  536.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  537.     }
  538.     else
  539.         _fstrcpy(lpszStyle,"Regular");
  540.     cf.lpszStyle = lpszStyle;
  541.     hdc = GetDC(lpgw->hWndGraph);
  542.     lf.lfHeight = -MulDiv(lpgw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  543.     ReleaseDC(lpgw->hWndGraph, hdc);
  544.     cf.lpLogFont = &lf;
  545.     cf.nFontType = SCREEN_FONTTYPE;
  546.     cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_USESTYLE;
  547.     if (ChooseFont(&cf)) {
  548.         _fstrcpy(lpgw->fontname,lf.lfFaceName);
  549.         lpgw->fontsize = cf.iPointSize / 10;
  550.         if (cf.nFontType & BOLD_FONTTYPE)
  551.             lstrcat(lpgw->fontname," Bold");
  552.         if (cf.nFontType & ITALIC_FONTTYPE)
  553.             lstrcat(lpgw->fontname," Italic");
  554.         SendMessage(lpgw->hWndGraph,WM_COMMAND,M_REBUILDTOOLS,0L);
  555.     }
  556. #endif
  557. }
  558.  
  559. /* ================================== */
  560.  
  561. static void dot(HDC hdc, int xdash, int ydash)
  562. {
  563.     MoveTo(hdc, xdash, ydash);
  564.     LineTo(hdc, xdash, ydash+1);
  565. }
  566.  
  567.  
  568. void
  569. drawgraph(LPGW lpgw, HDC hdc, LPRECT rect)
  570. {
  571.     int xdash, ydash;            /* the transformed coordinates */
  572.     int rr, rl, rt, rb;
  573.     struct GWOP FAR *curptr;
  574.     struct GWOPBLK *blkptr;
  575.     int htic, vtic;
  576.     int hshift, vshift;
  577.     unsigned int lastop=-1;        /* used for plotting last point on a line */
  578.     int pen, numsolid;
  579.     int polymax = 200;
  580.     int polyi = 0;
  581.     POINT *ppt;
  582.     unsigned int ngwop=0;
  583.     BOOL isColor;
  584.  
  585.     if (lpgw->locked) 
  586.         return;
  587.  
  588.      isColor= (GetDeviceCaps(hdc, PLANES)*GetDeviceCaps(hdc,BITSPIXEL)) > 2;
  589.     if (lpgw->background != RGB(255,255,255) && lpgw->color && isColor) {
  590.         SetBkColor(hdc,lpgw->background);
  591.         FillRect(hdc, rect, lpgw->hbrush);
  592.     }
  593.  
  594.     ppt = (POINT *)LocalAllocPtr(LHND, (polymax+1) * sizeof(POINT));
  595.  
  596.     rr = rect->right;
  597.     rl = rect->left;
  598.     rt = rect->top;
  599.     rb = rect->bottom;
  600.  
  601.     htic = lpgw->org_pointsize*MulDiv(lpgw->htic, rr-rl, lpgw->xmax) + 1;
  602.     vtic = lpgw->org_pointsize*MulDiv(lpgw->vtic, rb-rt, lpgw->ymax) + 1;
  603.  
  604.     lpgw->angle = 0;
  605.     SetFont(lpgw, hdc);
  606.     SetTextAlign(hdc, TA_LEFT|TA_BOTTOM);
  607.     vshift = MulDiv(lpgw->vchar, rb-rt, lpgw->ymax)/2;
  608.     /* HBB 980630: new variable for moving rotated text to the correct
  609.      * position: */
  610.     hshift = MulDiv(lpgw->vchar, rr-rl, lpgw->xmax)/2;
  611.  
  612.     pen = 0;
  613.     SelectObject(hdc, lpgw->hpen[pen]);
  614.     SelectObject(hdc, lpgw->colorbrush[pen+2]);
  615.     numsolid = lpgw->numsolid;
  616.  
  617.     /* do the drawing */
  618.     blkptr = lpgw->gwopblk_head;
  619.     curptr = NULL;
  620.     if (blkptr) {
  621.         if (!blkptr->gwop)
  622.             blkptr->gwop = (struct GWOP FAR *)GlobalLock(blkptr->hblk);
  623.         if (!blkptr->gwop)
  624.             return;
  625.         curptr = (struct GWOP FAR *)blkptr->gwop;
  626.     }
  627.     while(ngwop < lpgw->nGWOP)
  628.        {
  629.         /* transform the coordinates */
  630.         xdash = MulDiv(curptr->x, rr-rl-1, lpgw->xmax) + rl;
  631.         ydash = MulDiv(curptr->y, rt-rb+1, lpgw->ymax) + rb - 1;
  632.         if ((lastop==W_vect) && (curptr->op!=W_vect)) {
  633.             if (polyi >= 2)
  634.                 Polyline(hdc, ppt, polyi);
  635.             polyi = 0;
  636.         }
  637.         switch (curptr->op) {
  638.             case 0:    /* have run past last in this block */
  639.                 break;
  640.             case W_move:
  641.                 ppt[0].x = xdash;
  642.                 ppt[0].y = ydash;
  643.                 polyi = 1;
  644.                 break;
  645.             case W_vect:
  646.                 ppt[polyi].x = xdash;
  647.                 ppt[polyi].y = ydash;
  648.                 polyi++;
  649.                 if (polyi >= polymax) {
  650.                     Polyline(hdc, ppt, polyi);
  651.                     ppt[0].x = xdash;
  652.                     ppt[0].y = ydash;
  653.                     polyi = 1;;
  654.                 }
  655.                 break;
  656.             case W_line_type:
  657.                 switch (curptr->x)
  658.                 {
  659.                     case (WORD) -2:        /* black 2 pixel wide */
  660.                         SelectObject(hdc, lpgw->hbpen);
  661.                         if (lpgw->color && isColor)
  662.                             SetTextColor(hdc, lpgw->colorpen[0].lopnColor);
  663.                         break;
  664.                     case (WORD) -1:        /* black 1 pixel wide doted */
  665.                         SelectObject(hdc, lpgw->hapen);
  666.                         if (lpgw->color && isColor)
  667.                             SetTextColor(hdc, lpgw->colorpen[1].lopnColor);
  668.                         break;
  669.                     default:
  670.                         SelectObject(hdc, lpgw->hpen[(curptr->x)%WGNUMPENS]);
  671.                         if (lpgw->color && isColor)
  672.                             SetTextColor(hdc, lpgw->colorpen[(curptr->x)%WGNUMPENS + 2].lopnColor);
  673.                 }
  674.                 pen = curptr->x;
  675.                 SelectObject(hdc, lpgw->colorbrush[pen%WGNUMPENS + 2]);
  676.                 break;
  677.             case W_put_text:
  678.                 {char *str;
  679.                 str = LocalLock(curptr->htext);
  680.                 if (str) {
  681.                     /* HBB 980630: shift differently for rotated text: */
  682.                     if (lpgw->angle)
  683.                         xdash += hshift;
  684.                     else
  685.                     ydash += vshift;
  686.                     SetBkMode(hdc,TRANSPARENT);
  687.                     TextOut(hdc,xdash,ydash,str,lstrlen(str));
  688.                     SetBkMode(hdc,OPAQUE);
  689.                 }
  690.                 LocalUnlock(curptr->htext);
  691.                 }
  692.                 break;
  693.             case W_text_angle:
  694.                 lpgw->angle = curptr->x;
  695.                 SetFont(lpgw,hdc);
  696.                 break;
  697.             case W_justify:
  698.                 switch (curptr->x)
  699.                 {
  700.                     case LEFT:
  701.                         SetTextAlign(hdc, TA_LEFT|TA_BOTTOM);
  702.                         break;
  703.                     case RIGHT:
  704.                         SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
  705.                         break;
  706.                     case CENTRE:
  707.                         SetTextAlign(hdc, TA_CENTER|TA_BOTTOM);
  708.                         break;
  709.                     }
  710.                 break;
  711.             case W_pointsize:
  712.                 /* HBB 980309: term->pointsize() passes the number as a scaled-up
  713.                  * integer now, so we can avoid calling sscanf() here (in a Win16
  714.                  * DLL sharing stack with the stack-starved wgnuplot.exe !).
  715.                  */
  716.                 if (curptr->x != 0) {
  717.                     double pointsize = curptr->x / 100.0;
  718.                     /* HBB 980309: the older code didn't make *any* use of the
  719.                      * pointsize at all! That obviously can't be correct. So use it! */
  720.                     htic = pointsize*MulDiv(lpgw->htic, rr-rl, lpgw->xmax) + 1;
  721.                     vtic = pointsize*MulDiv(lpgw->vtic, rb-rt, lpgw->ymax) + 1;
  722.                                } else {
  723.                     char *str;
  724.                     str = LocalLock(curptr->htext);
  725.                     if (str) {
  726.                         double pointsize;
  727.                         sscanf(str, "%lg", &pointsize);
  728.                         htic = lpgw->org_pointsize*MulDiv(lpgw->htic, rr-rl, lpgw->xmax) + 1;
  729.                         vtic = lpgw->org_pointsize*MulDiv(lpgw->vtic, rb-rt, lpgw->ymax) + 1;
  730.                     }
  731.                     LocalUnlock(curptr->htext);
  732.                 }
  733.                 break;
  734.             default:    /* A plot mark */
  735.                 if (pen >= numsolid) {
  736.                     pen %= numsolid;    /* select solid pen */
  737.                     SelectObject(hdc, lpgw->hpen[pen]);
  738.                     SelectObject(hdc, lpgw->colorbrush[pen+2]);
  739.                 }
  740.                                 switch (curptr->op) {
  741.                     case W_dot:
  742.                         dot(hdc, xdash, ydash);
  743.                         break;
  744.                     case W_plus: /* do plus */ 
  745.                         MoveTo(hdc,xdash-htic,ydash);
  746.                         LineTo(hdc,xdash+htic+1,ydash);
  747.                         MoveTo(hdc,xdash,ydash-vtic);
  748.                         LineTo(hdc,xdash,ydash+vtic+1);
  749.                         break;
  750.                     case W_cross: /* do X */ 
  751.                         MoveTo(hdc,xdash-htic,ydash-vtic);
  752.                         LineTo(hdc,xdash+htic+1,ydash+vtic+1);
  753.                         MoveTo(hdc,xdash-htic,ydash+vtic);
  754.                         LineTo(hdc,xdash+htic+1,ydash-vtic-1);
  755.                         break;
  756.                     case W_star: /* do star */ 
  757.                         MoveTo(hdc,xdash-htic,ydash);
  758.                         LineTo(hdc,xdash+htic+1,ydash);
  759.                         MoveTo(hdc,xdash,ydash-vtic);
  760.                         LineTo(hdc,xdash,ydash+vtic+1);
  761.                         MoveTo(hdc,xdash-htic,ydash-vtic);
  762.                         LineTo(hdc,xdash+htic+1,ydash+vtic+1);
  763.                         MoveTo(hdc,xdash-htic,ydash+vtic);
  764.                         LineTo(hdc,xdash+htic+1,ydash-vtic-1);
  765.                         break;
  766.                     case W_circle: /* do open circle */ 
  767.                         Arc(hdc, xdash-htic, ydash-vtic, xdash+htic+1, ydash+vtic+1, xdash, ydash+vtic+1, xdash, ydash+vtic+1);
  768.                         dot(hdc, xdash, ydash);
  769.                         break;
  770.                     case W_fcircle: /* do filled circle */ 
  771.                             Ellipse(hdc, xdash-htic, ydash-vtic, xdash+htic+1, ydash+vtic+1);
  772.                         break;
  773.                     default:    /* Closed figure */
  774.                           {    POINT p[6];
  775.                             int i;
  776.                         int shape;
  777.                         int filled = 0;
  778.                         static float pointshapes[5][10] = {
  779.                             {-1, -1, +1, -1, +1, +1, -1, +1, 0, 0}, /* box */
  780.                             { 0, +1, -1,  0,  0, -1, +1,  0, 0, 0}, /* diamond */
  781.                             { 0, -4./3, -4./3, 2./3, 4./3,  2./3, 0, 0}, /* triangle */
  782.                             { 0, 4./3, -4./3, -2./3, 4./3,  -2./3, 0, 0}, /* inverted triangle */
  783.                             { 0, 1, 0.95106, 0.30902, 0.58779, -0.80902, -0.58779, -0.80902, -0.95106, 0.30902} /* pentagon (not used) */
  784.                         };
  785.                         switch (curptr->op) {
  786.                             case W_box:         shape = 0;    break;
  787.                             case W_diamond:        shape = 1;    break;
  788.                             case W_itriangle:    shape = 2;    break;
  789.                             case W_triangle:    shape = 3;    break;
  790.                             default:        shape = curptr->op-W_fbox;
  791.                                         filled = 1;
  792.                                         break;
  793.                         }
  794.                         
  795.                             for ( i = 0; i<5; ++i )
  796.                                 if ( pointshapes[shape][i*2+1] == 0 && pointshapes[shape][i*2] == 0 )
  797.                                     break;
  798.                             else {
  799.                                     p[i].x = xdash + htic*pointshapes[shape][i*2] + 0.5;
  800.                                         p[i].y = ydash + vtic*pointshapes[shape][i*2+1] + 0.5;
  801.                                     }
  802.                             if ( filled )
  803.                             /* Filled polygon */
  804.                                     Polygon(hdc, p, i);
  805.                             else {
  806.                                     /* Outline polygon */
  807.                                     p[i].x = p[0].x;
  808.                                     p[i].y = p[0].y;
  809.                                     Polyline(hdc, p, i+1);
  810.                                     dot(hdc, xdash, ydash);
  811.                             }
  812.                           }
  813.                 }
  814.         }
  815.         lastop = curptr->op;
  816.         ngwop++;
  817.         curptr++;
  818.         if ((unsigned)(curptr - blkptr->gwop) >= GWOPMAX) {
  819.             GlobalUnlock(blkptr->hblk);
  820.             blkptr->gwop = (struct GWOP FAR *)NULL;
  821.             blkptr = blkptr->next;
  822.             if (!blkptr->gwop)
  823.                 blkptr->gwop = (struct GWOP FAR *)GlobalLock(blkptr->hblk);
  824.             if (!blkptr->gwop)
  825.                     return;
  826.                 curptr = (struct GWOP FAR *)blkptr->gwop;
  827.         }
  828.     }
  829.     if (polyi >= 2)
  830.         Polyline(hdc, ppt, polyi);
  831.     LocalFreePtr(ppt);
  832. }
  833.  
  834. /* ================================== */
  835.  
  836. /* copy graph window to clipboard */
  837. void
  838. CopyClip(LPGW lpgw)
  839. {
  840.     RECT rect;
  841.     HDC mem;
  842.     HBITMAP bitmap;
  843.     HANDLE hmf;
  844.     GLOBALHANDLE hGMem;
  845.     LPMETAFILEPICT lpMFP;
  846.     HWND hwnd;
  847.     HDC hdc;
  848.  
  849.     hwnd = lpgw->hWndGraph;
  850.  
  851.     /* view the window */
  852.     if (IsIconic(hwnd))
  853.         ShowWindow(hwnd, SW_SHOWNORMAL);
  854.     BringWindowToTop(hwnd);
  855.     UpdateWindow(hwnd);
  856.  
  857.     /* get the context */
  858.     hdc = GetDC(hwnd);
  859.     GetClientRect(hwnd, &rect);
  860.     /* make a bitmap and copy it there */
  861.     mem = CreateCompatibleDC(hdc);
  862.     bitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left,
  863.             rect.bottom - rect.top);
  864.     if (bitmap) {
  865.         /* there is enough memory and the bitmaps OK */
  866.         SelectObject(mem, bitmap);
  867.         BitBlt(mem,0,0,rect.right - rect.left, 
  868.             rect.bottom - rect.top, hdc, rect.left,
  869.             rect.top, SRCCOPY);
  870.     }
  871.     else {
  872.         MessageBeep(MB_ICONHAND);
  873.         MessageBox(hwnd, "Insufficient Memory to Copy Clipboard", 
  874.             lpgw->Title, MB_ICONHAND | MB_OK);
  875.     }
  876.     DeleteDC(mem);
  877.     {
  878.     GW gwclip = *lpgw;
  879.     int windowfontsize = MulDiv(lpgw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  880.     int i;
  881.     gwclip.fontsize = MulDiv(windowfontsize, lpgw->ymax, rect.bottom);
  882.     gwclip.hfonth = gwclip.hfontv = 0;
  883.  
  884.     /* HBB 981203: scale up pens as well... */
  885.     for (i=0; i<WGNUMPENS+2; i++) {
  886.         if(gwclip.monopen[i].lopnWidth.x > 1)
  887.             gwclip.monopen[i].lopnWidth.x =
  888.                 MulDiv(gwclip.monopen[i].lopnWidth.x,
  889.                     gwclip.xmax, rect.right-rect.left);
  890.         if(gwclip.colorpen[i].lopnWidth.x > 1)
  891.             gwclip.colorpen[i].lopnWidth.x =
  892.                 MulDiv(gwclip.colorpen[i].lopnWidth.x,
  893.                     gwclip.xmax, rect.right-rect.left);
  894.     }
  895.  
  896.     rect.right = lpgw->xmax;
  897.     rect.bottom = lpgw->ymax;
  898.     
  899.     MakePens(&gwclip, hdc);
  900.     MakeFonts(&gwclip, &rect, hdc);
  901.  
  902.     ReleaseDC(hwnd, hdc);
  903.  
  904.     hdc = CreateMetaFile((LPSTR)NULL);
  905.  
  906. /* HBB 981203: According to Petzold, Metafiles shouldn't contain SetMapMode() calls: */
  907.     /*SetMapMode(hdc, MM_ANISOTROPIC);*/
  908. #ifdef WIN32
  909.     SetWindowExtEx(hdc, rect.right, rect.bottom, (LPSIZE)NULL);
  910. #else
  911.     SetWindowExt(hdc, rect.right, rect.bottom);
  912. #endif
  913.     drawgraph(&gwclip, hdc, (void *) &rect);
  914.     hmf = CloseMetaFile(hdc);
  915.     DestroyFonts(&gwclip);
  916.     DestroyPens(&gwclip);
  917.     }
  918.  
  919.     hGMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)sizeof(METAFILEPICT));
  920.     lpMFP = (LPMETAFILEPICT) GlobalLock(hGMem);
  921.     hdc = GetDC(hwnd);    /* get window size */
  922.     GetClientRect(hwnd, &rect);
  923.     /* in MM_ANISOTROPIC, xExt & yExt give suggested size in 0.01mm units */
  924.     lpMFP->mm = MM_ANISOTROPIC;
  925.     lpMFP->xExt = MulDiv(rect.right-rect.left, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
  926.     /* HBB 981203: Seems it should be LOGPIXELS_Y_, here, not _X_*/
  927.     lpMFP->yExt = MulDiv(rect.bottom-rect.top, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
  928.     lpMFP->hMF = hmf;
  929.     ReleaseDC(hwnd, hdc);
  930.     GlobalUnlock(hGMem);
  931.  
  932.     OpenClipboard(hwnd);
  933.     EmptyClipboard();
  934.     SetClipboardData(CF_METAFILEPICT,hGMem);
  935.     SetClipboardData(CF_BITMAP, bitmap);
  936.     CloseClipboard();
  937.     return;
  938. }
  939.  
  940. /* copy graph window to printer */
  941. void
  942. CopyPrint(LPGW lpgw)
  943. {
  944. #ifdef WIN32
  945.     DOCINFO docInfo;
  946. #endif
  947.  
  948. #if WINVER >= 0x030a
  949.     HDC printer;
  950.     DLGPROC lpfnAbortProc;
  951.     DLGPROC lpfnPrintDlgProc;
  952.     PRINTDLG pd;
  953.     HWND hwnd;
  954.     RECT rect;
  955.     PRINT pr;
  956.     UINT widabort;
  957.  
  958.     hwnd = lpgw->hWndGraph;
  959.  
  960.     _fmemset(&pd, 0, sizeof(PRINTDLG));
  961.     pd.lStructSize = sizeof(PRINTDLG);
  962.     pd.hwndOwner = hwnd;
  963.     pd.Flags = PD_PRINTSETUP | PD_RETURNDC;
  964.  
  965.     if (!PrintDlg(&pd))
  966.         return;
  967.     printer = pd.hDC;
  968.     if (NULL == printer)
  969.         return;    /* abort */
  970.  
  971.     if (!PrintSize(printer, hwnd, &rect)) {
  972.         DeleteDC(printer);
  973.         return; /* abort */
  974.     }
  975.  
  976.     pr.hdcPrn = printer;
  977.     SetWindowLong(hwnd, 4, (LONG)((LPPRINT)&pr));
  978. #ifdef WIN32
  979.     PrintRegister((LPPRINT)&pr);
  980. #endif
  981.  
  982.     EnableWindow(hwnd,FALSE);
  983.     pr.bUserAbort = FALSE;
  984. #ifdef WIN32
  985.     pr.hDlgPrint = CreateDialogParam(hdllInstance,"CancelDlgBox",hwnd,PrintDlgProc,(LPARAM)lpgw->Title);
  986.     SetAbortProc(printer,PrintAbortProc);  
  987.  
  988.     memset(&docInfo, 0, sizeof(DOCINFO));
  989.     docInfo.cbSize = sizeof(DOCINFO);
  990.     docInfo.lpszDocName = lpgw->Title;
  991.  
  992.     if (StartDoc(printer, &docInfo) > 0) {
  993. #else
  994. #ifdef __DLL__
  995.     lpfnPrintDlgProc = (DLGPROC)GetProcAddress(hdllInstance, "PrintDlgProc");
  996.     lpfnAbortProc = (DLGPROC)GetProcAddress(hdllInstance, "PrintAbortProc");
  997. #else
  998.     lpfnPrintDlgProc = (DLGPROC)MakeProcInstance((FARPROC)PrintDlgProc, hdllInstance);
  999.     lpfnAbortProc = (DLGPROC)MakeProcInstance((FARPROC)PrintAbortProc, hdllInstance);
  1000. #endif
  1001.     pr.hDlgPrint = CreateDialogParam(hdllInstance,"CancelDlgBox",hwnd,lpfnPrintDlgProc,(LPARAM)lpgw->Title);
  1002.     Escape(printer,SETABORTPROC,0,(LPSTR)lpfnAbortProc,NULL);  
  1003.     if (Escape(printer, STARTDOC, lstrlen(lpgw->Title),lpgw->Title, NULL) > 0) {
  1004. #endif
  1005.         SetMapMode(printer, MM_TEXT);
  1006.         SetBkMode(printer,OPAQUE);
  1007. #ifdef WIN32
  1008.         StartPage(printer);
  1009. #endif
  1010.         DestroyFonts(lpgw);
  1011.         MakeFonts(lpgw, (RECT FAR *)&rect, printer);
  1012.         DestroyPens(lpgw);    /* rebuild pens */
  1013.         MakePens(lpgw, printer);
  1014.         drawgraph(lpgw, printer, (void *) &rect);
  1015. #ifdef WIN32
  1016.         if (EndPage(printer) > 0)
  1017.             EndDoc(printer);
  1018. #else
  1019.         if (Escape(printer,NEWFRAME,0,NULL,NULL) > 0)
  1020.             Escape(printer,ENDDOC,0,NULL,NULL);
  1021. #endif
  1022.     }
  1023.     if (!pr.bUserAbort) {
  1024.         EnableWindow(hwnd,TRUE);
  1025.         DestroyWindow(pr.hDlgPrint);
  1026.     }
  1027. #ifndef WIN32
  1028. #ifndef __DLL__
  1029.     FreeProcInstance((FARPROC)lpfnPrintDlgProc);
  1030.     FreeProcInstance((FARPROC)lpfnAbortProc);
  1031. #endif
  1032. #endif
  1033.     DeleteDC(printer);
  1034.     SetWindowLong(hwnd, 4, (LONG)(0L));
  1035. #ifdef WIN32
  1036.     PrintUnregister((LPPRINT)&pr);
  1037. #endif
  1038.     /* make certain that the screen pen set is restored */
  1039.     SendMessage(lpgw->hWndGraph,WM_COMMAND,M_REBUILDTOOLS,0L);
  1040. #endif
  1041.     return;
  1042. }
  1043.  
  1044. /* ================================== */
  1045. /*  INI file stuff */
  1046. void
  1047. WriteGraphIni(LPGW lpgw)
  1048. {
  1049.     RECT rect;
  1050.     int i;
  1051.     char entry[32];
  1052.     LPLOGPEN pc;
  1053.     LPLOGPEN pm;
  1054.     LPSTR file = lpgw->IniFile;
  1055.     LPSTR section = lpgw->IniSection;
  1056.     char profile[80];
  1057.  
  1058.     if ((file == (LPSTR)NULL) || (section == (LPSTR)NULL))
  1059.         return;
  1060.     if (IsIconic(lpgw->hWndGraph))
  1061.         ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);
  1062.     GetWindowRect(lpgw->hWndGraph,&rect);
  1063.     wsprintf(profile, "%d %d", rect.left, rect.top);
  1064.     WritePrivateProfileString(section, "GraphOrigin", profile, file);
  1065.     wsprintf(profile, "%d %d", rect.right-rect.left, rect.bottom-rect.top);
  1066.     WritePrivateProfileString(section, "GraphSize", profile, file);
  1067.     wsprintf(profile, "%s,%d", lpgw->fontname, lpgw->fontsize);
  1068.     WritePrivateProfileString(section, "GraphFont", profile, file);
  1069.     wsprintf(profile, "%d", lpgw->color);
  1070.     WritePrivateProfileString(section, "GraphColor", profile, file);
  1071.     wsprintf(profile, "%d", lpgw->graphtotop);
  1072.     WritePrivateProfileString(section, "GraphToTop", profile, file);
  1073.     wsprintf(profile, "%d %d %d",GetRValue(lpgw->background),
  1074.             GetGValue(lpgw->background), GetBValue(lpgw->background));
  1075.     WritePrivateProfileString(section, "GraphBackground", profile, file);
  1076.  
  1077.     /* now save pens */
  1078.     for (i=0; i<WGNUMPENS+2; i++) {
  1079.         if (i==0)
  1080.             _fstrcpy(entry,"Border");
  1081.         else if (i==1)
  1082.             _fstrcpy(entry,"Axis");
  1083.         else
  1084.              wsprintf(entry,"Line%d",i-1);
  1085.         pc = &lpgw->colorpen[i];
  1086.         pm = &lpgw->monopen[i];
  1087.         wsprintf(profile, "%d %d %d %d %d",GetRValue(pc->lopnColor),
  1088.             GetGValue(pc->lopnColor), GetBValue(pc->lopnColor),
  1089.             (pc->lopnWidth.x != 1) ? -pc->lopnWidth.x : pc->lopnStyle, 
  1090.             (pm->lopnWidth.x != 1) ? -pm->lopnWidth.x : pm->lopnStyle);
  1091.         WritePrivateProfileString(section, entry, profile, file);
  1092.     }
  1093.     return;
  1094. }
  1095.  
  1096. void
  1097. ReadGraphIni(LPGW lpgw)
  1098. {
  1099.     LPSTR file = lpgw->IniFile;
  1100.     LPSTR section = lpgw->IniSection;
  1101.     char profile[81];
  1102.     char entry[32];
  1103.     LPSTR p;
  1104.     int i,r,g,b,colorstyle,monostyle;
  1105.     COLORREF ref;
  1106.     BOOL bOKINI;
  1107.  
  1108.     bOKINI = (file != (LPSTR)NULL) && (section != (LPSTR)NULL);
  1109.     if (!bOKINI)
  1110.         profile[0] = '\0';
  1111.  
  1112.     if (bOKINI)
  1113.       GetPrivateProfileString(section, "GraphOrigin", "", profile, 80, file);
  1114.     if ( (p = GetInt(profile, (LPINT)&lpgw->Origin.x)) == NULL)
  1115.         lpgw->Origin.x = CW_USEDEFAULT;
  1116.     if ( (p = GetInt(p, (LPINT)&lpgw->Origin.y)) == NULL)
  1117.         lpgw->Origin.y = CW_USEDEFAULT;
  1118.     if (bOKINI)
  1119.       GetPrivateProfileString(section, "GraphSize", "", profile, 80, file);
  1120.     if ( (p = GetInt(profile, (LPINT)&lpgw->Size.x)) == NULL)
  1121.         lpgw->Size.x = CW_USEDEFAULT;
  1122.     if ( (p = GetInt(p, (LPINT)&lpgw->Size.y)) == NULL)
  1123.         lpgw->Size.y = CW_USEDEFAULT;
  1124.  
  1125.     if (bOKINI)
  1126.       GetPrivateProfileString(section, "GraphFont", "", profile, 80, file);
  1127.     {
  1128.         char FAR *size;
  1129.         size = _fstrchr(profile,',');
  1130.         if (size) {
  1131.             *size++ = '\0';
  1132.             if ( (p = GetInt(size, (LPINT)&lpgw->fontsize)) == NULL)
  1133.                 lpgw->fontsize = WINFONTSIZE;
  1134.         }
  1135.         _fstrcpy(lpgw->fontname, profile);
  1136.         if (lpgw->fontsize == 0)
  1137.             lpgw->fontsize = WINFONTSIZE;
  1138.         if (!(*lpgw->fontname))
  1139.             if (LOWORD(GetVersion()) == 3)
  1140.                 _fstrcpy(lpgw->fontname,WIN30FONT);
  1141.             else
  1142.                 _fstrcpy(lpgw->fontname,WINFONT);
  1143.     }
  1144.  
  1145.     if (bOKINI)
  1146.       GetPrivateProfileString(section, "GraphColor", "", profile, 80, file);
  1147.         if ( (p = GetInt(profile, (LPINT)&lpgw->color)) == NULL)
  1148.             lpgw->color = TRUE;
  1149.  
  1150.     if (bOKINI)
  1151.       GetPrivateProfileString(section, "GraphToTop", "", profile, 80, file);
  1152.         if ( (p = GetInt(profile, (LPINT)&lpgw->graphtotop)) == NULL)
  1153.             lpgw->graphtotop = TRUE;
  1154.  
  1155.     lpgw->background = RGB(255,255,255);
  1156.     if (bOKINI)
  1157.       GetPrivateProfileString(section, "GraphBackground", "", profile, 80, file);
  1158.     if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1159.          ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1160.          ((p = GetInt(p, (LPINT)&b)) != NULL) )
  1161.             lpgw->background = RGB(r,g,b);
  1162.  
  1163.     StorePen(lpgw, 0,RGB(0,0,0),PS_SOLID,PS_SOLID);
  1164.     if (bOKINI)
  1165.       GetPrivateProfileString(section, "Border", "", profile, 80, file);
  1166.     if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1167.          ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1168.          ((p = GetInt(p, (LPINT)&b)) != NULL) &&
  1169.          ((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
  1170.          ((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
  1171.             StorePen(lpgw,0,RGB(r,g,b),colorstyle,monostyle);
  1172.  
  1173.     StorePen(lpgw, 1,RGB(192,192,192),PS_DOT,PS_DOT);
  1174.     if (bOKINI)
  1175.       GetPrivateProfileString(section, "Axis", "", profile, 80, file);
  1176.     if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1177.          ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1178.          ((p = GetInt(p, (LPINT)&b)) != NULL) &&
  1179.          ((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
  1180.          ((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
  1181.             StorePen(lpgw,1,RGB(r,g,b),colorstyle,monostyle);
  1182.  
  1183.     for (i=0; i<WGNUMPENS; i++)
  1184.     {
  1185.         ref = wginitcolor[ i%WGDEFCOLOR ];
  1186.         colorstyle = wginitstyle[ (i/WGDEFCOLOR) % WGDEFSTYLE ];
  1187.         monostyle  = wginitstyle[ i%WGDEFSTYLE ];
  1188.         StorePen(lpgw, i+2,ref,colorstyle,monostyle);
  1189.         wsprintf(entry,"Line%d",i+1);
  1190.         if (bOKINI)
  1191.           GetPrivateProfileString(section, entry, "", profile, 80, file);
  1192.         if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1193.              ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1194.              ((p = GetInt(p, (LPINT)&b)) != NULL) &&
  1195.              ((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
  1196.              ((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
  1197.                 StorePen(lpgw,i+2,RGB(r,g,b),colorstyle,monostyle);
  1198.     }
  1199. }
  1200.  
  1201.  
  1202. /* ================================== */
  1203.  
  1204. #define LS_DEFLINE 2
  1205. typedef struct tagLS {
  1206.     int    widtype;
  1207.     int    wid;
  1208.     HWND    hwnd;
  1209.     int    pen;            /* current pen number */
  1210.     LOGPEN    colorpen[WGNUMPENS+2];    /* logical color pens */
  1211.     LOGPEN    monopen[WGNUMPENS+2];    /* logical mono pens */
  1212. } LS;
  1213. typedef LS FAR*  LPLS;
  1214.     
  1215.  
  1216. COLORREF
  1217. GetColor(HWND hwnd, COLORREF ref)
  1218. {
  1219. CHOOSECOLOR cc;
  1220. COLORREF aclrCust[16];
  1221. int i;
  1222.  
  1223.     for (i=0; i<16; i++) {
  1224.         aclrCust[i] = RGB(0,0,0);
  1225.     }
  1226.     _fmemset(&cc, 0, sizeof(CHOOSECOLOR));
  1227.     cc.lStructSize = sizeof(CHOOSECOLOR);
  1228.     cc.hwndOwner = hwnd;
  1229.     cc.lpCustColors = aclrCust;
  1230.     cc.rgbResult = ref;
  1231.     cc.Flags = CC_RGBINIT;
  1232.     if (ChooseColor(&cc))
  1233.         return cc.rgbResult;
  1234.     return ref;
  1235. }
  1236.  
  1237.  
  1238. /* force update of owner draw button */
  1239. void
  1240. UpdateColorSample(HWND hdlg)
  1241. {
  1242.     RECT rect;
  1243.     POINT ptul, ptlr;
  1244.     GetWindowRect( GetDlgItem(hdlg, LS_COLORSAMPLE), &rect);
  1245.     ptul.x = rect.left;
  1246.     ptul.y = rect.top;
  1247.     ptlr.x = rect.right;
  1248.     ptlr.y = rect.bottom;
  1249.     ScreenToClient(hdlg, &ptul);
  1250.     ScreenToClient(hdlg, &ptlr);
  1251.     rect.left   = ptul.x;
  1252.     rect.top    = ptul.y;
  1253.     rect.right  = ptlr.x;
  1254.     rect.bottom = ptlr.y;
  1255.     InvalidateRect(hdlg, &rect, TRUE);
  1256.     UpdateWindow(hdlg);
  1257. }
  1258.  
  1259. BOOL CALLBACK WINEXPORT
  1260. LineStyleDlgProc(HWND hdlg, UINT wmsg, WPARAM wparam, LPARAM lparam)
  1261. {
  1262.     char buf[16];
  1263.     LPLS lpls;
  1264.     int i;
  1265.     UINT pen;
  1266.     LPLOGPEN plpm, plpc;
  1267.     lpls = (LPLS)GetWindowLong(GetParent(hdlg), 4);
  1268.  
  1269.     switch (wmsg) {
  1270.         case WM_INITDIALOG:
  1271.             pen = 2;
  1272.             for (i=0; i<WGNUMPENS+2; i++) {
  1273.                 if (i==0)
  1274.                     _fstrcpy(buf,"Border");
  1275.                 else if (i==1)
  1276.                     _fstrcpy(buf,"Axis");
  1277.                 else
  1278.                      wsprintf(buf,"Line%d",i-1);
  1279.                 SendDlgItemMessage(hdlg, LS_LINENUM, LB_ADDSTRING, 0, 
  1280.                     (LPARAM)((LPSTR)buf));
  1281.             }
  1282.             SendDlgItemMessage(hdlg, LS_LINENUM, LB_SETCURSEL, pen, 0L);
  1283.  
  1284.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1285.                 (LPARAM)((LPSTR)"Solid"));
  1286.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1287.                 (LPARAM)((LPSTR)"Dash"));
  1288.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1289.                 (LPARAM)((LPSTR)"Dot"));
  1290.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1291.                 (LPARAM)((LPSTR)"DashDot"));
  1292.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1293.                 (LPARAM)((LPSTR)"DashDotDot"));
  1294.  
  1295.             plpm = &lpls->monopen[pen];
  1296.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1297.                 plpm->lopnStyle, 0L);
  1298.             wsprintf(buf,"%d",plpm->lopnWidth.x);
  1299.             SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1300.  
  1301.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1302.                 (LPARAM)((LPSTR)"Solid"));
  1303.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1304.                 (LPARAM)((LPSTR)"Dash"));
  1305.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1306.                 (LPARAM)((LPSTR)"Dot"));
  1307.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1308.                 (LPARAM)((LPSTR)"DashDot"));
  1309.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1310.                 (LPARAM)((LPSTR)"DashDotDot"));
  1311.  
  1312.             plpc = &lpls->colorpen[pen];
  1313.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1314.                 plpc->lopnStyle, 0L);
  1315.             wsprintf(buf,"%d",plpc->lopnWidth.x);
  1316.             SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1317.  
  1318.             return TRUE;
  1319.         case WM_COMMAND:
  1320.             pen = (UINT)SendDlgItemMessage(hdlg, LS_LINENUM, LB_GETCURSEL, 0, 0L);
  1321.             plpm = &lpls->monopen[pen];
  1322.             plpc = &lpls->colorpen[pen];
  1323.             switch (LOWORD(wparam)) {
  1324.                 case LS_LINENUM:
  1325.                     wsprintf(buf,"%d",plpm->lopnWidth.x);
  1326.                     SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1327.                     SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1328.                         plpm->lopnStyle, 0L);
  1329.                     wsprintf(buf,"%d",plpc->lopnWidth.x);
  1330.                     SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1331.                     SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1332.                         plpc->lopnStyle, 0L);
  1333.                     UpdateColorSample(hdlg);
  1334.                     return FALSE;
  1335.                 case LS_MONOSTYLE:
  1336.                     plpm->lopnStyle = 
  1337.                         (UINT)SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_GETCURSEL, 0, 0L);
  1338.                     if (plpm->lopnStyle != 0) {
  1339.                         plpm->lopnWidth.x = 1;
  1340.                         wsprintf(buf,"%d",plpm->lopnWidth.x);
  1341.                         SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1342.                     }
  1343.                     return FALSE;
  1344.                 case LS_MONOWIDTH:
  1345.                     GetDlgItemText(hdlg, LS_MONOWIDTH, buf, 15);
  1346.                     GetInt(buf, (LPINT)&plpm->lopnWidth.x);
  1347.                     if (plpm->lopnWidth.x != 1) {
  1348.                         plpm->lopnStyle = 0;
  1349.                         SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1350.                             plpm->lopnStyle, 0L);
  1351.                     }
  1352.                     return FALSE;
  1353.                 case LS_CHOOSECOLOR:
  1354.                     plpc->lopnColor = GetColor(hdlg, plpc->lopnColor);
  1355.                     UpdateColorSample(hdlg);
  1356.                     return FALSE;
  1357.                 case LS_COLORSTYLE:
  1358.                     plpc->lopnStyle = 
  1359.                         (UINT)SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_GETCURSEL, 0, 0L);
  1360.                     if (plpc->lopnStyle != 0) {
  1361.                         plpc->lopnWidth.x = 1;
  1362.                         wsprintf(buf,"%d",plpc->lopnWidth.x);
  1363.                         SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1364.                     }
  1365.                     return FALSE;
  1366.                 case LS_COLORWIDTH:
  1367.                     GetDlgItemText(hdlg, LS_COLORWIDTH, buf, 15);
  1368.                     GetInt(buf, (LPINT)&plpc->lopnWidth.x);
  1369.                     if (plpc->lopnWidth.x != 1) {
  1370.                         plpc->lopnStyle = 0;
  1371.                         SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1372.                             plpc->lopnStyle, 0L);
  1373.                     }
  1374.                     return FALSE;
  1375.                 case LS_DEFAULT:
  1376.                     plpm = lpls->monopen;
  1377.                     plpc = lpls->colorpen;
  1378.                     /* border */
  1379.                     plpc->lopnColor   = RGB(0,0,0);
  1380.                     plpc->lopnStyle   = PS_SOLID;
  1381.                     plpc->lopnWidth.x = 1;
  1382.                     plpm->lopnStyle   = PS_SOLID;
  1383.                     plpm->lopnWidth.x = 1;
  1384.                     plpc++; plpm++;
  1385.                     /* axis */
  1386.                     plpc->lopnColor   = RGB(192,192,192);
  1387.                     plpc->lopnStyle   = PS_DOT;
  1388.                     plpc->lopnWidth.x = 1;
  1389.                     plpm->lopnStyle   = PS_DOT;
  1390.                     plpm->lopnWidth.x = 1;
  1391.                     /* LineX */
  1392.                     for (i=0; i<WGNUMPENS; i++) {
  1393.                         plpc++; plpm++;
  1394.                         plpc->lopnColor   = wginitcolor[ i%WGDEFCOLOR ];
  1395.                         plpc->lopnStyle   = wginitstyle[ (i/WGDEFCOLOR) % WGDEFSTYLE ];
  1396.                         plpc->lopnWidth.x = 1;
  1397.                         plpm->lopnStyle   = wginitstyle[ i%WGDEFSTYLE ];
  1398.                         plpm->lopnWidth.x = 1;
  1399.                     }
  1400.                     /* update window */
  1401.                     plpm = &lpls->monopen[pen];
  1402.                     plpc = &lpls->colorpen[pen];
  1403.                     SendDlgItemMessage(hdlg, LS_LINENUM, LB_SETCURSEL, pen, 0L);
  1404.                     wsprintf(buf,"%d",plpm->lopnWidth.x);
  1405.                     SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1406.                     SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1407.                         plpm->lopnStyle, 0L);
  1408.                     wsprintf(buf,"%d",plpc->lopnWidth.x);
  1409.                     SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1410.                     SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1411.                         plpc->lopnStyle, 0L);
  1412.                     UpdateColorSample(hdlg);
  1413.                     return FALSE;
  1414.                 case IDOK:
  1415.                     EndDialog(hdlg, IDOK);
  1416.                     return TRUE;
  1417.                 case IDCANCEL:
  1418.                     EndDialog(hdlg, IDCANCEL);
  1419.                     return TRUE;
  1420.             }
  1421.             break;
  1422.         case WM_DRAWITEM:
  1423.             {
  1424.             HBRUSH hBrush;
  1425.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lparam;
  1426.             pen = (UINT)SendDlgItemMessage(hdlg, LS_LINENUM, LB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  1427.             plpc = &lpls->colorpen[pen];
  1428.             hBrush = CreateSolidBrush(plpc->lopnColor);
  1429.             FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
  1430.             FrameRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)GetStockObject(BLACK_BRUSH));
  1431.             DeleteObject(hBrush);
  1432.             }
  1433.             return FALSE;
  1434.     }
  1435.     return FALSE;
  1436. }
  1437.  
  1438.  
  1439.  
  1440. /* GetWindowLong(hwnd, 4) must be available for use */
  1441. BOOL
  1442. LineStyle(LPGW lpgw)
  1443. {
  1444. DLGPROC lpfnLineStyleDlgProc ;
  1445. BOOL status = FALSE;
  1446. LS ls;
  1447.     
  1448.     SetWindowLong(lpgw->hWndGraph, 4, (LONG)((LPLS)&ls));
  1449.     _fmemcpy(&ls.colorpen, &lpgw->colorpen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1450.     _fmemcpy(&ls.monopen, &lpgw->monopen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1451.  
  1452. #ifdef WIN32
  1453.     if (DialogBox (hdllInstance, "LineStyleDlgBox", lpgw->hWndGraph, LineStyleDlgProc)
  1454. #else
  1455. #ifdef __DLL__
  1456.     lpfnLineStyleDlgProc = (DLGPROC)GetProcAddress(hdllInstance, "LineStyleDlgProc");
  1457. #else
  1458.     lpfnLineStyleDlgProc = (DLGPROC)MakeProcInstance((FARPROC)LineStyleDlgProc, hdllInstance);
  1459. #endif
  1460.     if (DialogBox (hdllInstance, "LineStyleDlgBox", lpgw->hWndGraph, lpfnLineStyleDlgProc)
  1461. #endif
  1462.         == IDOK) {
  1463.         _fmemcpy(&lpgw->colorpen, &ls.colorpen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1464.         _fmemcpy(&lpgw->monopen, &ls.monopen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1465.         status = TRUE;
  1466.     }
  1467. #ifndef WIN32
  1468. #ifndef __DLL__
  1469.     FreeProcInstance((FARPROC)lpfnLineStyleDlgProc);
  1470. #endif
  1471. #endif
  1472.     SetWindowLong(lpgw->hWndGraph, 4, (LONG)(0L));
  1473.     return status;
  1474. }
  1475.  
  1476. /* ================================== */
  1477.  
  1478. LRESULT CALLBACK WINEXPORT
  1479. WndGraphProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1480. {
  1481.     HDC hdc;
  1482.     PAINTSTRUCT ps;
  1483.     RECT rect;
  1484.     LPGW lpgw;
  1485.     HMENU sysmenu;
  1486.     int i;
  1487.  
  1488.     lpgw = (LPGW)GetWindowLong(hwnd, 0);
  1489.  
  1490.     switch(message)
  1491.     {
  1492.         case WM_SYSCOMMAND:
  1493.             switch(LOWORD(wParam))
  1494.             {
  1495.                 case M_GRAPH_TO_TOP:
  1496.                 case M_COLOR:
  1497.                 case M_CHOOSE_FONT:
  1498.                 case M_COPY_CLIP:
  1499.                 case M_LINESTYLE:
  1500.                 case M_BACKGROUND:
  1501.                 case M_PRINT:
  1502.                 case M_WRITEINI:
  1503.                 case M_REBUILDTOOLS:
  1504.                     SendMessage(hwnd, WM_COMMAND, wParam, lParam);
  1505.                     break;
  1506.                 case M_ABOUT:
  1507.                     if (lpgw->lptw)
  1508.                         AboutBox(hwnd,lpgw->lptw->AboutText);
  1509.                     return 0;
  1510.                 case M_COMMANDLINE:
  1511.                     sysmenu = GetSystemMenu(lpgw->hWndGraph,0);
  1512.                     i = GetMenuItemCount (sysmenu);
  1513.                     DeleteMenu (sysmenu, --i, MF_BYPOSITION);
  1514.                     DeleteMenu (sysmenu, --i, MF_BYPOSITION);
  1515.                     ShowWindow (lpgw->lptw->hWndParent, SW_SHOW);
  1516.                     break;
  1517.             }
  1518.             break;
  1519.         case WM_COMMAND:
  1520.             switch(LOWORD(wParam))
  1521.             {
  1522.                 case M_GRAPH_TO_TOP:
  1523.                     lpgw->graphtotop = !lpgw->graphtotop;
  1524.                     SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1525.                     return(0);
  1526.                 case M_COLOR:
  1527.                     lpgw->color = !lpgw->color;
  1528.                     SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1529.                     return(0);
  1530.                 case M_CHOOSE_FONT:
  1531.                     SelFont(lpgw);
  1532.                     return 0;
  1533.                 case M_COPY_CLIP:
  1534.                     CopyClip(lpgw);
  1535.                     return 0;
  1536.                 case M_LINESTYLE:
  1537.                     if (LineStyle(lpgw))
  1538.                         SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1539.                     return 0;
  1540.                 case M_BACKGROUND:
  1541.                     lpgw->background = GetColor(hwnd, lpgw->background);
  1542.                     SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1543.                     return 0;
  1544.                 case M_PRINT:
  1545.                     CopyPrint(lpgw);
  1546.                     return 0;
  1547.                 case M_WRITEINI:
  1548.                     WriteGraphIni(lpgw);
  1549.                     if (lpgw->lptw)
  1550.                         WriteTextIni(lpgw->lptw);
  1551.                     return 0;
  1552.                 case M_REBUILDTOOLS:
  1553.                     lpgw->resized = TRUE;
  1554.                     if (lpgw->color) 
  1555.                         CheckMenuItem(lpgw->hPopMenu, M_COLOR, MF_BYCOMMAND | MF_CHECKED);
  1556.                     else
  1557.                         CheckMenuItem(lpgw->hPopMenu, M_COLOR, MF_BYCOMMAND | MF_UNCHECKED);
  1558.                     if (lpgw->graphtotop) 
  1559.                         CheckMenuItem(lpgw->hPopMenu, M_GRAPH_TO_TOP, MF_BYCOMMAND | MF_CHECKED);
  1560.                     else
  1561.                         CheckMenuItem(lpgw->hPopMenu, M_GRAPH_TO_TOP, MF_BYCOMMAND | MF_UNCHECKED);
  1562.                     DestroyPens(lpgw);
  1563.                     DestroyFonts(lpgw);
  1564.                     hdc = GetDC(hwnd);
  1565.                     MakePens(lpgw, hdc);
  1566.                     GetClientRect(hwnd, &rect);
  1567.                     MakeFonts(lpgw, (LPRECT)&rect, hdc);
  1568.                     ReleaseDC(hwnd, hdc);
  1569.                     GetClientRect(hwnd, &rect);
  1570.                     InvalidateRect(hwnd, (LPRECT) &rect, 1);
  1571.                     UpdateWindow(hwnd);
  1572.                     return 0;
  1573.             }
  1574.             return 0;
  1575.         case WM_RBUTTONDOWN:
  1576.             {
  1577.             POINT pt;
  1578.             pt.x = LOWORD(lParam);
  1579.             pt.y = HIWORD(lParam);
  1580.             ClientToScreen(hwnd,&pt);
  1581.             TrackPopupMenu(lpgw->hPopMenu, TPM_LEFTALIGN, 
  1582.                 pt.x, pt.y, 0, hwnd, NULL);
  1583.             }
  1584.             return(0);
  1585.         case WM_CREATE:
  1586.             lpgw = ((CREATESTRUCT FAR *)lParam)->lpCreateParams;
  1587.             SetWindowLong(hwnd, 0, (LONG)lpgw);
  1588.             lpgw->hWndGraph = hwnd;
  1589.             hdc = GetDC(hwnd);
  1590.             MakePens(lpgw, hdc);
  1591.             GetClientRect(hwnd, &rect);
  1592.             MakeFonts(lpgw, (LPRECT)&rect, hdc);
  1593.             ReleaseDC(hwnd, hdc);
  1594. #if WINVER >= 0x030a
  1595.             {
  1596.             WORD version = LOWORD(GetVersion());
  1597.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1598.                 if ( lpgw->lptw && (lpgw->lptw->DragPre!=(LPSTR)NULL) && (lpgw->lptw->DragPost!=(LPSTR)NULL) )
  1599.                     DragAcceptFiles(hwnd, TRUE);
  1600.             }
  1601. #endif
  1602.             return(0);
  1603.         case WM_PAINT:
  1604.             hdc = BeginPaint(hwnd, &ps);
  1605.             SetMapMode(hdc, MM_TEXT);
  1606.             SetBkMode(hdc,OPAQUE);
  1607.             GetClientRect(hwnd, &rect);
  1608. #ifdef WIN32
  1609.             SetViewportExtEx(hdc, rect.right, rect.bottom, NULL);
  1610. #else
  1611.             SetViewportExt(hdc, rect.right, rect.bottom);
  1612. #endif
  1613.             drawgraph(lpgw, hdc, (void *) &rect);
  1614.             EndPaint(hwnd, &ps);
  1615.             return 0;
  1616.         case WM_SIZE:
  1617.             /* update font sizes if graph resized */
  1618.             if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED)) {
  1619.                 RECT rect;
  1620.                 SendMessage(hwnd,WM_SYSCOMMAND,M_REBUILDTOOLS,0L);
  1621.                 GetWindowRect(hwnd,&rect);
  1622.                 lpgw->Size.x = rect.right-rect.left;
  1623.                 lpgw->Size.y = rect.bottom-rect.top;
  1624.             }
  1625.             break;
  1626. #if WINVER >= 0x030a
  1627.         case WM_DROPFILES:
  1628.             {
  1629.             WORD version = LOWORD(GetVersion());
  1630.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1631.                 if (lpgw->lptw)
  1632.                     DragFunc(lpgw->lptw, (HDROP)wParam);
  1633.             }
  1634.             break;
  1635. #endif
  1636.         case WM_DESTROY:
  1637.             DestroyPens(lpgw);
  1638.             DestroyFonts(lpgw);
  1639. #if __TURBOC__ >= 0x410    /* Borland C++ 3.1 or later */
  1640.             {
  1641.             WORD version = LOWORD(GetVersion());
  1642.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1643.                 DragAcceptFiles(hwnd, FALSE);
  1644.             }
  1645. #endif
  1646.             if (lpgw->lptw && !IsWindowVisible(lpgw->lptw->hWndParent)) {
  1647.                 PostMessage (lpgw->lptw->hWndParent, WM_CLOSE, 0, 0);
  1648.             }
  1649.             return 0;
  1650.         case WM_CLOSE:
  1651.             GraphClose(lpgw);
  1652.             return 0;
  1653.         }
  1654.     return DefWindowProc(hwnd, message, wParam, lParam);
  1655. }
  1656.  
  1657.